import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { UtilService } from '@main/shared/services/util.service';
import { SysUserService } from '../system/user/user.service';
import { SysMenuService } from '../system/menu/menu.service';
import { isEmpty } from 'lodash';
// import { InjectRepository } from '@nestjs/typeorm';
// import { Repository } from 'typeorm';
// import SysUserRole from '@main/entities/service/admin/sys/sys-user-role.entity';
import { ApiException } from '@main/common/exceptions/api.exception';
import { RedisService } from '@main/shared/services/redis.service';
import { SysLogService } from '../system/log/log.service';

// import { GatherMachineService } from './../gather/machine/machine.service';

interface TreeNode {
  menuId: number;
  parentMenuId: number | null;
  children?: TreeNode[] | null;
}

function buildTree(nodes: TreeNode[]): TreeNode[] {
  const map: { [key: number]: TreeNode } = {};

  nodes.forEach((node) => {
    map[node.menuId] = { ...node, children: null };
  });

  const tree: TreeNode[] = [];

  nodes.forEach((node) => {
    if (node.parentMenuId === -1) {
      if (!node.children) {
        node.children = [];
      }
      tree.push(map[node.menuId]);
    } else {
      const parent = map[node.parentMenuId];
      if (parent) {
        if (!parent.children) {
          parent.children = [];
        }
        parent.children.push(map[node.menuId]);
      }
    }
  });

  return tree;
}

@Injectable()
export class LoginService {
  constructor(
    private redisService: RedisService,
    private userService: SysUserService,
    private menuService: SysMenuService,
    private logService: SysLogService,
    private util: UtilService,
    private jwtService: JwtService,
    // private gatherMachineService: GatherMachineService
  ) {}

  async getLoginSign(userName: string, password: string, ip: string, ua: string) {
    const user = await this.userService.findUserByUserName(userName);

    if (isEmpty(user)) {
      throw new ApiException(10003);
    }

    const comparePassword = this.util.md5(`${password}${user.psalt}`);

    if (user.password !== comparePassword) {
      throw new ApiException(10003);
    }

    const perms = await this.menuService.getPerms(user.id);

    if (user.id === '1') {
      const oldToken = await this.getRedisTokenById(user.id);
      if (oldToken) {
        this.logService.saveLoginLog(user.id, ip, ua);
        return oldToken;
      }
    }

    const redis = await this.redisService.getRedis();

    const pv = Number(await redis.get(`admin:passwordVersion:${user.id}`)) || 1;

    const jwtSign = this.jwtService.sign(
      {
        uid: user.id,
        pv,
        userName: user.userName,
        nickName: user.nickName,
      }
      // {
      //   expiresIn: '24h',
      // },
    );

    await redis.set(`admin:passwordVersion:${user.id}`, pv);
    // Token设置过期时间 24小时
    await redis.set(`admin:token:${user.id}`, jwtSign, 'EX', 60 * 60 * 24);

    await redis.set(`admin:perms:${user.id}`, JSON.stringify(perms));

    await this.logService.saveLoginLog(user.id, ip, ua);

    return jwtSign;

    // return '';

    // const comparePassword = this.util.md5(`${password}${user.psalt}`);

    // if (user.password !== comparePassword) {
    //   throw new ApiException(10003);
    // }

    // const roleRows = await this.userRoleRepository.find({
    //   where: { userId: user.id },
    // });

    // const roles = roleRows.map((e) => {
    //   return e.roleId;
    // });

    // user['roles'] = roles;

    // const menuList = await this.menuService.getMenus(user.id);

    // user['permissions'] = menuList.map(item=>item.menuCode);

    // user['menuList'] = buildTree(menuList as any);

    // if (userName === 'admin' && password === 'admin123' && !menuList.length) {
    //   user['permissions'] = ['*:*'];
    // }

    // delete user['password'];

    // delete user['psalt'];

    // return IpcSuccessException(user);
  }

  async getRedisTokenById(id: string): Promise<string> {
    return this.redisService.getRedis().get(`admin:token:${id}`);
  }

  async getRedisPermsById(id: number): Promise<string> {
    return this.redisService.getRedis().get(`admin:perms:${id}`);
  }

  async getRedisPasswordVersionById(id: number): Promise<string> {
    return this.redisService.getRedis().get(`admin:passwordVersion:${id}`);
  }

  /**
   * 清除登录状态信息
   */
  async clearLoginStatus(uid: number): Promise<void> {
    await this.userService.forbidden(uid);

    // await this.gatherMachineService.clearMachineConnectFn();
  }

  /**
   * 获取权限菜单
   */
  async getPermMenu(uid: string) {
    const menus = await this.menuService.getMenus(uid);
    const permissions = menus.map((item) => item.menuCode);
    const perms = await this.menuService.getPerms(uid);
    return { menuList: buildTree(menus), perms, permissions };

    // return { menuList:[], perms:[], permissions:[] };
  }
}
